package cn.schoolwow.util.module.query.resource.flow.walkResource;

import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.resource.QueryResource;
import cn.schoolwow.util.domain.query.resource.QueryResourceResponse;
import cn.schoolwow.util.module.query.resource.domain.FileFilterOption;
import cn.schoolwow.util.module.query.resource.domain.ResourceQueryOption;
import cn.schoolwow.util.module.query.resource.domain.SingleQueryResourceHandler;
import cn.schoolwow.util.module.query.resource.flow.walkResource.common.SetUrlFileFlow;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class WalkResourceFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        flowContext.executeFlowList(new SetUrlFileFlow());
        file(flowContext);
        jar(flowContext);
    }

    @Override
    public String name() {
        return "遍历文件路径";
    }

    private void file(FlowContext flowContext) throws IOException {
        String urlFile = (String) flowContext.checkData("urlFile");
        URL url = (URL) flowContext.checkData("url");
        ResourceQueryOption resourceQueryOption = (ResourceQueryOption) flowContext.checkData("resourceQueryOption");

        if(!"file".equalsIgnoreCase(url.getProtocol())){
            return;
        }
        FileFilterOption fileFilterOption = resourceQueryOption.fileFilterOption;
        SingleQueryResourceHandler singleQueryResourceHandler = fileFilterOption.singleQueryResourceHandler;

        File baseDirectory = new File(urlFile);
        if (!baseDirectory.isDirectory()) {
            throw new IllegalArgumentException("["+resourceQueryOption.name+"]路径不是文件夹!路径:" + resourceQueryOption.path);
        }
        Files.walkFileTree(baseDirectory.toPath(), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                File f = file.toFile();
                //过滤文件
                if(null!=fileFilterOption.fileName&&!f.getName().equalsIgnoreCase(fileFilterOption.fileName)){
                    return FileVisitResult.CONTINUE;
                }
                if(!fileFilterOption.fileNameStartWithList.isEmpty()){
                    boolean exist = false;
                    for(String fileNameStartWith:fileFilterOption.fileNameStartWithList){
                        if(f.getName().startsWith(fileNameStartWith)){
                            exist = true;
                            break;
                        }
                    }
                    if(!exist){
                        return FileVisitResult.CONTINUE;
                    }
                }
                if(!fileFilterOption.fileNameEndWithList.isEmpty()){
                    boolean exist = false;
                    for(String fileNameEndWith:fileFilterOption.fileNameEndWithList){
                        if(f.getName().endsWith(fileNameEndWith)){
                            exist = true;
                            break;
                        }
                    }
                    if(!exist){
                        return FileVisitResult.CONTINUE;
                    }
                }

                QueryResourceResponse queryResourceResponse = QueryResource
                        .newQuery(f.getName(), f.getAbsolutePath())
                        .execute();
                if(singleQueryResourceHandler.handleQueryResourceResponse(queryResourceResponse)){
                    return FileVisitResult.CONTINUE;
                }else{
                    return FileVisitResult.TERMINATE;
                }
            }

            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                if(resourceQueryOption.fileFilterOption.ignoreDirectory){
                    return FileVisitResult.CONTINUE;
                }
                File f = dir.toFile();
                if(null!=fileFilterOption.fileName&&!f.getName().equalsIgnoreCase(fileFilterOption.fileName)){
                    return FileVisitResult.CONTINUE;
                }
                //过滤文件
                if(!fileFilterOption.fileNameStartWithList.isEmpty()){
                    boolean exist = false;
                    for(String fileNameStartWith:fileFilterOption.fileNameStartWithList){
                        if(f.getName().startsWith(fileNameStartWith)){
                            exist = true;
                            break;
                        }
                    }
                    if(!exist){
                        return FileVisitResult.CONTINUE;
                    }
                }
                if(!fileFilterOption.fileNameEndWithList.isEmpty()){
                    boolean exist = false;
                    for(String fileNameEndWith:fileFilterOption.fileNameEndWithList){
                        if(f.getName().endsWith(fileNameEndWith)){
                            exist = true;
                            break;
                        }
                    }
                    if(!exist){
                        return FileVisitResult.CONTINUE;
                    }
                }
                QueryResourceResponse queryResourceResponse = QueryResource
                        .newQuery(f.getName(), f.getAbsolutePath())
                        .execute();
                if(singleQueryResourceHandler.handleQueryResourceResponse(queryResourceResponse)){
                    return FileVisitResult.CONTINUE;
                }else{
                    return FileVisitResult.TERMINATE;
                }
            }
        });
    }

    private void jar(FlowContext flowContext) throws IOException {
        String urlFile = (String) flowContext.checkData("urlFile");
        URL url = (URL) flowContext.checkData("url");
        ResourceQueryOption resourceQueryOption = (ResourceQueryOption) flowContext.checkData("resourceQueryOption");

        if(!"jar".equalsIgnoreCase(url.getProtocol())){
            return;
        }
        FileFilterOption fileFilterOption = resourceQueryOption.fileFilterOption;
        SingleQueryResourceHandler singleQueryResourceHandler = fileFilterOption.singleQueryResourceHandler;

        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
        if(null==jarURLConnection){
            throw new IllegalArgumentException("["+resourceQueryOption.name+"]路径不存在!路径:" + resourceQueryOption.path);
        }
        JarFile jarFile = jarURLConnection.getJarFile();
        if(null==jarFile){
            throw new IllegalArgumentException("["+resourceQueryOption.name+"]路径不存在!路径:" + resourceQueryOption.path);
        }
        Enumeration<JarEntry> jarEntries = jarFile.entries();
        while (jarEntries.hasMoreElements()) {
            JarEntry jarEntry = jarEntries.nextElement();
            String jarEntryName = jarEntry.getName();

            String fileName = jarEntryName.substring(jarEntryName.lastIndexOf("/")+1);
            //过滤文件
            if(null!=fileFilterOption.fileName&&!fileName.equalsIgnoreCase(fileFilterOption.fileName)){
                continue;
            }
            if(!fileFilterOption.fileNameStartWithList.isEmpty()){
                boolean exist = false;
                for(String fileNameStartWith:fileFilterOption.fileNameStartWithList){
                    if(fileName.startsWith(fileNameStartWith)){
                        exist = true;
                        break;
                    }
                }
                if(!exist){
                    continue;
                }
            }
            if(!fileFilterOption.fileNameEndWithList.isEmpty()){
                boolean exist = false;
                for(String fileNameEndWith:fileFilterOption.fileNameEndWithList){
                    if(fileName.endsWith(fileNameEndWith)){
                        exist = true;
                        break;
                    }
                }
                if(!exist){
                    continue;
                }
            }
            if(!jarEntryName.contains(urlFile)){
                continue;
            }
            //排除文件夹
            if(jarEntryName.endsWith("/")){
                continue;
            }
            QueryResourceResponse queryResourceResponse = QueryResource
                    .newQuery(fileName, jarEntryName)
                    .execute();
            if(!singleQueryResourceHandler.handleQueryResourceResponse(queryResourceResponse)){
                break;
            }
        }
    }
}
